﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using MovieModels;
using System.Threading;
using MKDataBase.Contracts;
using MK_Movie_Manager.EditMovieDeails;

namespace MK_Movie_Manager
{
    public partial class MKMovieManager_MainForm : Form
    {
        private ToolTip MKManagerToolTips;
        private static AboutBox aboutMM;
        private MovieDetailsComponent movieDetails;
        private MovieDetailsEditComponent editMovieDetails;
        private IDBProvider MovieDB;

        public MKMovieManager_MainForm()
        {
            this.MovieDB = MMSettings.CurrentDBInstance;
            InitializeComponent();
            aboutMM = new AboutBox();
            editMovieDetails = new MovieDetailsEditComponent();
            movieDetails = new MovieDetailsComponent(editMovieDetails, EditMovieDetails_Click);            
            MKManagerToolTips = new ToolTip();
            MKManagerToolTips.SetToolTip(this.pbSearchImages, "Search Movie Images");
            MKManagerToolTips.SetToolTip(this.pbExploreDirectory, "Read Movies From Directory");
            MKManagerToolTips.SetToolTip(this.pbHome, "MovieManager Home.");
        }

        private void searchIMDBToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.mainPanel.Controls.Clear();
            SearchComponent searchForm = new SearchComponent(this);
            this.mainPanel.Controls.Add(searchForm);
            searchForm.Show();
        }

        public static List<MovieManagerDataRow> moviesInDB;

        private void MKMovieManager_MainForm_Load(object sender, EventArgs e)
        {
            ReadMoviesFromDB();
        }

        #region SidePanel
        /// <summary>
        /// Reads the movies from DB.
        /// </summary>
        public void ReadMoviesFromDB()
        {
            //Read DB and Populate values in side panel
            moviesInDB = this.MovieDB.GetMovies();
            UpdateSidePanel();
        }

        /// <summary>
        /// Updates the side panel.
        /// </summary>
        private void UpdateSidePanel(List<MovieManagerDataRow> filteredMovies=null)
        {
            this.sidePanel.Controls.Clear();
            int i = 0;
            var movies = filteredMovies ?? moviesInDB;
            movies.ForEach(movie =>
                {
                    SimpleMovieCompponent com = new SimpleMovieCompponent(i + 1, movie.MovieName, movie.MovieID, this.smcClick, this.movieDeleteCLick, this.MovieDB);
                    com.Location = new System.Drawing.Point(-2, 2 + (i * 17));
                    com.Name = "simpleMovieCompponent" + i;
                    com.Size = new System.Drawing.Size(235, 17);
                    com.TabIndex = 0;
                    com.MouseEnter += new EventHandler(com_MouseEnter);
                    this.sidePanel.Controls.Add(com);
                    i++;
                });

        }

        /// <summary>
        /// Movies the delete C lick.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        void movieDeleteCLick(object sender, EventArgs e)
        {
            this.mainPanel.Controls.Clear();
            ReadMoviesFromDB();
        }

        /// <summary>
        /// Handles the MouseEnter event of the com control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        void com_MouseEnter(object sender, EventArgs e)
        {
            //Hide all other buttons
            this.sidePanel.Controls.OfType<SimpleMovieCompponent>().ToList().ForEach(m => m.HideDeleteButton());

            var obj = sender as SimpleMovieCompponent;
            obj.ShowDeleteButton();
        }
        #endregion

        #region Explore Directory
        /// <summary>
        /// Handles the Click event of the pbExploreDirectory control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void pbExploreDirectory_Click(object sender, EventArgs e)
        {
            SearchAndUpdate src = new SearchAndUpdate(this.MovieDB, this);
            this.mainPanel.Controls.Clear();
            this.mainPanel.Controls.Add(src);
            src.Show();
        }
        #endregion

        #region SearchImage
        private SearchPopupControl SearchImagePopUp;
        private void pbSearchImage_Click(object sender, EventArgs e)
        {

            System.EventHandler temphandler = new EventHandler(PreformSearchImageAction);
            //Close any other search popup opened
            this.Controls.OfType<SearchPopupControl>().ToList().ForEach(c => c.Dispose());

            SearchImagePopUp = new SearchPopupControl(this.pbSearchImages, temphandler);
            this.Controls.Add(SearchImagePopUp);
            SearchImagePopUp.BringToFront();
        }
        private void PreformSearchImageAction(object o, EventArgs e)
        {
            try
            {
                IEnumerable<BingImageSearchResult> res = BingImageSearchResult.SearchMoviesByName(SearchImagePopUp.searchString);
                ImageSearchResultComponent comp = new ImageSearchResultComponent(res);
                this.mainPanel.Controls.Clear();
                this.mainPanel.Controls.Add(comp);
            }
            catch
            {
                MessageBox.Show("Unable to communicate to BingService.Please Try Later.");
            }

        }
        #endregion

        #region CloseForm
        private void pbClose_Click(object sender, EventArgs e)
        {
            this.Close();
        }
        #endregion

        #region SearchMovies
        private SearchPopupControl SearchMoviePopup;
        private void pbSearchMovies_Click(object sender, EventArgs e)
        {
            //Close any other search popup opened
            this.Controls.OfType<SearchPopupControl>().ToList().ForEach(c => c.Dispose());
            SearchMoviePopup = new SearchPopupControl(this.pbSearchMovies, this.PreformSearchMovieAction);
            this.Controls.Add(SearchMoviePopup);
            SearchMoviePopup.BringToFront();
        }
        private void PreformSearchMovieAction(object o, EventArgs e)
        {
            var searchString = this.SearchMoviePopup.searchString;
            if (!string.IsNullOrWhiteSpace(searchString))
            {
                bingSearchBGWorker.RunWorkerAsync(searchString);
            }
        }
        private void bingSearchBGWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            string searchString = Convert.ToString(e.Argument);
            try
            {
                e.Result = BingSearchResult.SearchMoviesByName(searchString);
            }
            catch
            {
                MessageBox.Show("Unable tio communicate to BingService.Please Try Later.");
            }
        }
        private void bingSearchBGWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            var BingSearchResult = e.Result as IList<BingSearchResult>;
            if (BingSearchResult != null && BingSearchResult.Any())
            {
                int i = 0;
                this.mainPanel.Controls.Clear();
                BingSearchResult.ToList().ForEach(b =>
                    {
                        var searchRes = new SearchResultComponent(b);
                        searchRes.Location = new Point(5, 5 + (i * 65));
                        this.mainPanel.Controls.Add(searchRes);
                        i++;
                    });
            }
        }
        #endregion

        #region DisplayMovieDetails

        internal void smcClick(object sender, LinkLabelLinkClickedEventArgs e)
        {
            var obj = (SimpleMovieLinkLabel)sender;
            var id = obj.movieid;
            DisplayMovieDetails(obj.Text, id);
        }

        internal void DisplayMovieDetails(string movietitle, int id = 0)
        {
            //wait for previous search pending
            if (ImdbSearchBGWorker.IsBusy)
                return;

            //Verify if movie exists in db,if not then search in IMDB
            var result = this.MovieDB.GetMovieDetailsById(id);

            if (result == null)
            {
                DialogResult mbres = MessageBox.Show("Movie Details Not Found.Searh in IMDB?", "Warning", MessageBoxButtons.YesNo);
                if (mbres.Equals(DialogResult.Yes))
                {
                    this.mainPanel.Controls.Clear();
                    //Add mainpanel label
                    this.mainPanel.Controls.Add(this.mainPanelCenterLabel);
                    this.mainPanelCenterLabel.Text = string.Format("Getting '{0}' Movie Details From IMDB.........", movietitle);
                    ImdbSearchBGWorker.RunWorkerAsync(new { Title = movietitle, Id = id });
                }
                return;
            }
            //if (this.mainPanel.Controls.OfType<MovieDetailsComponent>().Count() <= 0)
            //    this.mainPanel.Controls.Clear();
            IMDBMovie movie = new IMDBMovie().MapDBRowToIMDBMovie(result);
            ShowMovieDetails(movie, result.MovieImage, true);
        }

        private void ShowMovieDetails(IMDBMovie movie, byte[] p, bool isFromDB)
        {
            this.movieDetails.UpDateMovieDetails(movie, movie.Id);
            if (isFromDB)
            {
                this.movieDetails.SetImage(p);
                this.movieDetails.DisableAddButton();
            }
            // Movie Details is showing just update the value
            if (this.mainPanel.Controls.OfType<MovieDetailsComponent>().Count() <= 0)
            {
                this.mainPanel.Controls.Clear();
                this.mainPanel.Controls.Add(this.movieDetails);
            }
        }

        private void ImdbSearchBGWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            dynamic arg = e.Argument;
            string movietitle = arg.Title as string;
            int Id = arg.Id;
            try
            {
                var res = IMDBMovie.SearchMovie(movietitle, false);
                res.Id = Id;
                e.Result = res;
            }
            catch
            {
                MessageBox.Show("Unable to retrive Information from IMDB.Please check network connectivity.");
            }
        }

        private void ImdbSearchBGWorkver_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            //Clear the main panel
            //this.mainPanel.Controls.Clear();
            IMDBMovie movieDetails = e.Result as IMDBMovie;
            if (movieDetails != null)
                ShowMovieDetails(movieDetails, null, false);
            else
                this.mainPanel.Controls.Clear();
            //detailForm.Show();/
        }

        private void EditMovieDetails_Click(object sender, EventArgs e)
        {
            if (this.mainPanel.Controls.OfType<MovieDetailsEditComponent>().Count() <= 0)
            {
                this.mainPanel.Controls.Clear();
                this.mainPanel.Controls.Add(this.editMovieDetails);
            }
        }

        #endregion

        #region toolbar events

        private void pbHome_Click(object sender, EventArgs e)
        {
            this.mainPanel.Controls.Clear();
            this.mainPanel.Controls.AddRange(new Control[] { this.pbLogo, this.pbMainView });
        }

        private void pbInformation_Click(object sender, EventArgs e)
        {
            aboutMM.ShowDialog();
        }

        private void pbSettings_Click(object sender, EventArgs e)
        {
            //var rr = new MovieManagerSettings();
            //this.mainPanel.Controls.Clear();
            //this.mainPanel.Controls.Add(rr);
        }

        private void tbSearch_TextChanged(object sender, EventArgs e)
        {
            var searchStr = ((TextBox)sender).Text.ToUpper();
            var filtteredMovies = moviesInDB.Where(m => m.MovieName.ToUpper().Contains(searchStr));
            UpdateSidePanel(filtteredMovies.ToList());
        }

        #endregion

        #region Clipboard events
        /// <summary>
        /// Handles the LinkClicked event of the linklblClear control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.LinkLabelLinkClickedEventArgs"/> instance containing the event data.</param>
        private void linklblClear_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            this.rtbClipBoard.Clear();
        }

        /// <summary>
        /// Handles the Enter event of the rtbClipBoard control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void rtbClipBoard_Enter(object sender, EventArgs e)
        {
            this.rtbClipBoard.Text = this.rtbClipBoard.Text.Trim() + Environment.NewLine;
        }

        /// <summary>
        /// Handles the LinkClicked event of the lnkLblCopy control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.LinkLabelLinkClickedEventArgs"/> instance containing the event data.</param>
        private void lnkLblCopy_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            this.rtbClipBoard.Copy();
        }

        #endregion
        
    }
}
